package com.aura.common.redis.service;

import com.aura.common.core.utils.JsonUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.LinkedHashSet;
import java.util.Set;

/**
 * @ClassName RedisZSetService
 * @Description
 * @Author ZJX
 * @Date 2025/7/19 23:54
 * @Version 1.0
 **/
@Component
@SuppressWarnings(value = {"unchecked", "rawtypes"})
public class RedisZSetService {
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 向有序集合 ZSet 中添加元素
     *
     * @param key Redis key
     * @param value 元素值
     * @param score 分数（用于排序）
     * @param <T> 元素类型
     */
    public <T> void addMemberZSet(final String key, T value, double score) {
        redisTemplate.opsForZSet().add(key, value, score);
    }

    /**
     * 从有序集合 ZSet 中删除指定元素
     *
     * @param key Redis key
     * @param value 要删除的元素
     * @param <T> 元素类型
     */
    public <T> void delMemberZSet(final String key, T value) {
        redisTemplate.opsForZSet().remove(key, value);
    }

    /**
     * 根据排序分值删除
     *
     * @param key key
     * @param minScore 最小分
     * @param maxScore 最大分
     */
    public void removeZSetByScore(final String key, double minScore, double maxScore){
        redisTemplate.opsForZSet().removeRangeByScore(key,minScore,maxScore);
    }

    /**
     * 获取有序集合数据（支持复杂的泛型嵌套）
     *
     * @param key key信息
     * @param typeReference 类型模板
     * @return 有序集合
     * @param <T> 对象类型
     */
    public <T> Set<T> getCacheZSet(final String key, TypeReference<LinkedHashSet<T>> typeReference) {
        Set data = redisTemplate.opsForZSet().range(key, 0, -1);
        return JsonUtil.string2Obj(JsonUtil.obj2String(data), typeReference);
    }

    /**
     * 降序获取有序集合（支持复杂的泛型嵌套）
     * @param key key信息
     * @param typeReference 类型模板
     * @return 降序的有序集合
     * @param <T> 对象类型信息
     */
    public <T> Set<T> getCacheZSetDesc(final String key, TypeReference<LinkedHashSet<T>> typeReference) {
        Set data = redisTemplate.opsForZSet().reverseRange(key, 0, -1);
        return JsonUtil.string2Obj(JsonUtil.obj2String(data), typeReference);
    }

    /**
     * 获取 ZSet 中某个成员的分数
     *
     * @param key key
     * @param value 元素值
     * @param <T> 元素类型
     * @return 分数（null 表示不存在）
     */
    public <T> Double getScore(final String key, T value) {
        return redisTemplate.opsForZSet().score(key, value);
    }

    /**
     * 获取 ZSet 中某个成员的排名（从小到大，0 表示第一名）
     *
     * @param key key
     * @param value 元素值
     * @param <T> 元素类型
     * @return 排名（null 表示不存在）
     */
    public <T> Long getRank(final String key, T value) {
        return redisTemplate.opsForZSet().rank(key, value);
    }

    /**
     * 获取 ZSet 中某个成员的排名（从大到小，0 表示第一名）
     *
     * @param key key
     * @param value 元素值
     * @param <T> 元素类型
     * @return 排名（null 表示不存在）
     */
    public <T> Long getReverseRank(final String key, T value) {
        return redisTemplate.opsForZSet().reverseRank(key, value);
    }

    /**
     * 获取 ZSet 集合的元素个数
     *
     * @param key Redis key
     * @return 元素个数
     */
    public long getZSetSize(final String key) {
        Long size = redisTemplate.opsForZSet().size(key);
        return size == null ? 0 : size;
    }

    /**
     * 获取指定分数范围内的元素（正序）
     * 使用 LinkedHashSet保留插入顺序
     * @param key key
     * @param minScore 最小分数
     * @param maxScore 最大分数
     * @param offset 起始偏移
     * @param count 获取数量
     * @param typeReference 类型引用
     * @return 区间元素集合
     * @param <T> 类型
     */
    public <T> Set<T> getZSetByScore(final String key, double minScore, double maxScore,
                                     long offset, long count, TypeReference<LinkedHashSet<T>> typeReference) {
        Set data = redisTemplate.opsForZSet().rangeByScore(key, minScore, maxScore, offset, count);
        return JsonUtil.string2Obj(JsonUtil.obj2String(data), typeReference);
    }


}
